#ifndef ____SSBASEL__SSBASE__BASE_WEAK_PTR__H__
#define ____SSBASEL__SSBASE__BASE_WEAK_PTR__H__


#include "base.h"
#include "base_refcounted.h"
#include "base_scoped_ref_ptr.h"

_SSL_BEGIN
_SSBASEL_BEGIN

template <bool>
struct CompileAssert {
};

#undef COMPILE_ASSERT
#define COMPILE_ASSERT(expr, msg) \
	typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]

template <typename T> class supports_weak_ptr;
template <typename T> class weak_ptr;

#pragma warning(push)
#pragma warning(disable:4251)
class SSBASE_CLASS weak_reference
{
public:
	// Although Flag is bound to a specific thread, it may be deleted from another
	// via base::WeakPtr::~WeakPtr().
	class e_flag : virtual public ref_counted_base {
	public:
		e_flag();

		void invalidate();
		bool is_valid() const;

	private:
		friend class ref_counted_base;
		virtual ~e_flag(); // Fix compile error
		bool is_valid_;
	};

	weak_reference();
	explicit weak_reference(const e_flag* flag);
	~weak_reference();

	bool is_valid() const;

private:
	scoped_ref_ptr<const e_flag> flag_;
};

class SSBASE_CLASS weak_reference_owner
{
public:
	weak_reference_owner();
	~weak_reference_owner();

	weak_reference get_ref() const;

	bool has_refs() const {
		return flag_.get() && !flag_->has_one_ref();
	}

	void invalidate();

private:
	mutable scoped_ref_ptr<weak_reference::e_flag> flag_;
};

// This class simplifies the implementation of WeakPtr's type conversion
// constructor by avoiding the need for a public accessor for ref_.  A
// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
// base class gives us a way to access ref_ in a protected fashion.
class SSBASE_CLASS weakPtr_base
{
public:
	weakPtr_base();
	~weakPtr_base();

protected:
	explicit weakPtr_base(const weak_reference& ref);

	weak_reference ref_;
};

// This class provides a common implementation of common functions that would
// otherwise get instantiated separately for each distinct instantiation of
// SupportsWeakPtr<>.
class supports_weak_ptr_base
{
public:
	// A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
	// conversion will only compile if there is exists a Base which inherits
	// from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
	// function that makes calling this easier.
	template<typename Derived>
	static weak_ptr<Derived> static_as_weak_ptr(Derived* t) {
		typedef
			is_convertible<Derived, supports_weak_ptr_base&> convertible;
		COMPILE_ASSERT(convertible::value,
			AsWeakPtr_argument_inherits_from_SupportsWeakPtr);
		return as_weak_ptr_impl<Derived>(t, *t);
	}

private:
	// This template function uses type inference to find a Base of Derived
	// which is an instance of SupportsWeakPtr<Base>. We can then safely
	// static_cast the Base* to a Derived*.
	template <typename Derived, typename Base>
	static weak_ptr<Derived> as_weak_ptr_impl(
		Derived* t, const supports_weak_ptr<Base>&) {
			weak_ptr<Base> ptr = t->Base::AsWeakPtr();
			return weak_ptr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));
	}
};


template <typename T> class weak_ptr_factory;

// The WeakPtr class holds a weak reference to |T*|.
//
// This class is designed to be used like a normal pointer.  You should always
// null-test an object of this class before using it or invoking a method that
// may result in the underlying object being destroyed.
//
// EXAMPLE:
//
//   class Foo { ... };
//   WeakPtr<Foo> foo;
//   if (foo)
//     foo->method();
//
template <typename T>
class weak_ptr : public weakPtr_base
{
public:
	weak_ptr() : ptr_(NULL) {
	}

	// Allow conversion from U to T provided U "is a" T. Note that this
	// is separate from the (implicit) copy constructor.
	template <typename U>
	weak_ptr(const weak_ptr<U>& other) : weakPtr_base(other), ptr_(other.ptr_) {
	}

	T* get() const { return ref_.is_valid() ? ptr_ : NULL; }

	T& operator*() const {
		SS_ASSERT(get() != NULL);
		return *get();
	}
	T* operator->() const {
		SS_ASSERT(get() != NULL);
		return get();
	}

	// Allow WeakPtr<element_type> to be used in boolean expressions, but not
	// implicitly convertible to a real bool (which is dangerous).
	//
	// Note that this trick is only safe when the == and != operators
	// are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2"
	// will compile but do the wrong thing (i.e., convert to Testable
	// and then do the comparison).
private:
	typedef T* weak_ptr::*Testable;

public:
	operator Testable() const { return get() ? &weak_ptr::ptr_ : NULL; }

	void reset() {
		ref_ = weak_reference();
		ptr_ = NULL;
	}

private:
	// Explicitly declare comparison operators as required by the bool
	// trick, but keep them private.
	template <class U> bool operator==(weak_ptr<U> const&) const;
	template <class U> bool operator!=(weak_ptr<U> const&) const;

	friend class supports_weak_ptr_base;
	template <typename U> friend class weak_ptr;
	friend class supports_weak_ptr<T>;
	friend class weak_ptr_factory<T>;

	weak_ptr(const weak_reference& ref, T* ptr)
		: weakPtr_base(ref),
		ptr_(ptr) {
	}

	// This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
	// value is undefined (as opposed to NULL).
	T* ptr_;
};

// A class may be composed of a WeakPtrFactory and thereby
// control how it exposes weak pointers to itself.  This is helpful if you only
// need weak pointers within the implementation of a class.  This class is also
// useful when working with primitive types.  For example, you could have a
// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
template <class T>
class weak_ptr_factory
{
public:
	explicit weak_ptr_factory(T* ptr) : ptr_(ptr) {
	}

	~weak_ptr_factory() {
		ptr_ = NULL;
	}

	weak_ptr<T> get_weak_ptr() {
		SS_ASSERT(ptr_);
		return weak_ptr<T>(weak_reference_owner_.get_ref(), ptr_);
	}

	// Call this method to invalidate all existing weak pointers.
	void invalidate_weak_ptrs() {
		SS_ASSERT(ptr_);
		weak_reference_owner_.invalidate();
	}

	// Call this method to determine if any weak pointers exist.
	bool has_weak_ptrs() const {
		SS_ASSERT(ptr_);
		return weak_reference_owner_.has_refs();
	}

private:
	weak_reference_owner weak_reference_owner_;
	T* ptr_;
	DISALLOW_CLASS_IMPLICIT_CONSTRUCTORS(weak_ptr_factory);
};

// A class may extend from SupportsWeakPtr to let others take weak pointers to
// it. This avoids the class itself implementing boilerplate to dispense weak
// pointers.  However, since SupportsWeakPtr's destructor won't invalidate
// weak pointers to the class until after the derived class' members have been
// destroyed, its use can lead to subtle use-after-destroy issues.
template <class T>
class supports_weak_ptr : public supports_weak_ptr_base
{
public:
	supports_weak_ptr() {}

	weak_ptr<T> as_weak_ptr() {
		return weak_ptr<T>(weak_reference_owner_.get_ref(), static_cast<T*>(this));
	}

protected:
	~supports_weak_ptr() {}

private:
	weak_reference_owner weak_reference_owner_;
	DISALLOW_CLASS_COPY_AND_ASSIGN(supports_weak_ptr);
};

// Helper function that uses type deduction to safely return a WeakPtr<Derived>
// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
// extends a Base that extends SupportsWeakPtr<Base>.
//
// EXAMPLE:
//   class Base : public base::SupportsWeakPtr<Producer> {};
//   class Derived : public Base {};
//
//   Derived derived;
//   base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
//
// Note that the following doesn't work (invalid type conversion) since
// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
// the caller.
//
//   base::WeakPtr<Derived> ptr = derived.AsWeakPtr();  // Fails.

template <typename Derived>
weak_ptr<Derived> as_weak_ptr(Derived* t)
{
	return supports_weak_ptr_base::static_as_weak_ptr<Derived>(t);
}
#pragma warning(pop)

_SSBASEL_END
_SSL_END

#endif
